package com.lmxdawn.api.common.session;

import cn.hutool.core.date.SystemClock;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.lmxdawn.api.common.session.model.LoginModel;
import com.lmxdawn.api.common.session.model.LoginUser;
import com.lmxdawn.api.common.session.model.Token;
import com.lmxdawn.api.common.util.WebUtils;
import com.lmxdawn.api.dnf.service.IWebLoginService;
import lombok.experimental.UtilityClass;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.Objects;

/**
 * 会话辅助类
 *
 * @author jy
 * @since 2023-12-04 13:36
 */
@UtilityClass
public class SessionHelper {
    
    /**
     * 登录
     *
     * @param loginUser  要登录的用户对象
     * @param loginModel 登录配置
     */
    public static String login(LoginUser loginUser, LoginModel loginModel) {
        HttpServletRequest request = WebUtils.getRequest();
        return login(loginUser, loginModel, request);
    }
    
    /**
     * 登录
     *
     * @param loginUser  要登录的用户对象
     * @param loginModel 登录配置
     * @param request    当前请求
     * @return
     */
    public static String login(LoginUser loginUser, LoginModel loginModel, HttpServletRequest request) {
        Objects.requireNonNull(loginUser, "loginUser 不允许为空");
        Objects.requireNonNull(loginModel, "loginModel 不允许为空");
        Objects.requireNonNull(request, "request 不允许为空");
        // 用户会话
        UserSession userSession = createUserSession(loginUser, loginModel);
        // Token 签名
        Token token = createToken(loginModel, request);
        userSession.setToken(Collections.singletonList(token));
        // 登录
        getSessionStrategy().login(userSession, request, null);
        return token.getValue();
    }
    
    /**
     * 退出
     */
    public static void logout(HttpServletRequest request, HttpServletResponse response) {
        getSessionStrategy().logout(request, response);
    }
    
    /**
     * 踢人下线，根据账号id
     *
     * @param loginId 账号id
     */
    public static void kickout(Object loginId) {
        getSessionStrategy().kickout(loginId);
        if (Objects.nonNull(loginId)) {
            SpringUtil.getBean(IWebLoginService.class).refreshPermissionCache(String.valueOf(loginId));
        }
    }
    
    /**
     * 返回基于Redis实现的SessionStrategy
     */
    public static SessionStrategy getSessionStrategy() {
        return SpringUtil.getBean("RedisSession", SessionStrategy.class);
    }
    
    /**
     * 创建 UserSession
     * @param loginUser 登录用户对象
     * @return
     */
    private static UserSession createUserSession(LoginUser loginUser, LoginModel loginModel) {
        UserSession userSession = new UserSession();
        userSession.setId(loginUser.getId());
        userSession.setUsername(loginUser.getUsername());
        userSession.setRealName(loginUser.isRealName());
        userSession.setDisplayName(loginUser.getDisplayName());
        userSession.setTenantId(loginUser.getTenantId());
        userSession.setIsConcurrent(loginModel.isConcurrent());
        userSession.setTipRead(loginUser.isTipRead());
        return userSession;
    }

    
    /**
     * 创建 Token
     * @param loginModel 登录配置
     * @return
     */
    private static Token createToken(LoginModel loginModel, HttpServletRequest request) {
        Token token = new Token();
        token.setDevice(loginModel.getDevice());
        token.setTimeout(loginModel.getTimeout());
        token.setCreateTime(SystemClock.now());
        token.setUpdateTime(token.getCreateTime());
        token.setValue(IdUtil.fastSimpleUUID());
        token.setIp(ServletUtil.getClientIP(request));
        return token;
    }
    
}
